package com.yyf.file.service.impl;

import com.yyf.file.config.MinIOConfig;
import com.yyf.file.config.MinIOConfigProperties;
import com.yyf.file.service.FileStorageService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;

@Slf4j
@EnableConfigurationProperties(MinIOConfigProperties.class)
@Import(MinIOConfig.class)
public class MinIOFileStorageService implements FileStorageService {
    @Resource
    private MinioClient minioClient;
    @Resource
    private MinIOConfigProperties minIOConfigProperties;
    private static final String separator = "/";

/**
 * 构建文件上传的目录
 * @param dirPath
 * @param filename
 * @return
 */
    public String builderFilePath(String dirPath , String filename){
        StringBuilder stringBuilder=new StringBuilder(50);
        if(StringUtils.isNoneBlank(dirPath)){
            stringBuilder.append(dirPath).append(separator);
        }
        DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy/MM/dd");
        String todayStr= LocalDate.now().format(dateTimeFormatter);
        //想起来SimpleDateFormat是线程不安全的，避免格式异常
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
//        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }


    /**
     * 上传图片文件
     *
     * @param prefix
     * @param filename
     * @param inputStream
     * @return
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
        String filePath=builderFilePath(prefix,filename);
        try{
            PutObjectArgs putObjectArgs=PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket())
                    //当partSize = -1时，使用 MinIO 客户端的默认分块大小（通常为5MB）
                    .stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath=new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        }catch (Exception e){
            log.error("上传文件失败",e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传html文件
     *
     * @param prefix
     * @param filename
     * @param inputStream
     * @return
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath=builderFilePath(prefix,filename);
        try {
            PutObjectArgs putObjectArgs=PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("text/html")
                    .bucket(minIOConfigProperties.getBucket())
                    .stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath=new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception e) {
            log.error("minio put file error.",e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     *
     * @param pathUrl
     */
    @Override
    public void delete(String pathUrl) {
        String key=pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index=key.indexOf(separator);
        String bucker=key.substring(0,index);
        String filePath=key.substring(index+1);
        //删除object
       RemoveObjectArgs   removeObjectArgs=RemoveObjectArgs.builder()
                .bucket(bucker)
                .object(filePath)
                .build();
        try {
            minioClient.removeObject(removeObjectArgs);
        }catch (Exception e){
            log.error("minio remove file error.  pathUrl:{}",pathUrl);
            log.error("异常:{}",pathUrl);

        }
    }

    /**
     * download文件
     * @param pathUrl
     */
    @Override
    public byte[] downLoadFile(String pathUrl) {
        String key=pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index=key.indexOf(separator);
        String bucket=key.substring(0,index);
        String filePath=key.substring(index+1);
        InputStream inputStream=null;
        try {

            inputStream=minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(minIOConfigProperties.getBucket())
                            .object(filePath)
                            .build());

        }catch (Exception e){
            log.error("minio down file error.  pathUrl:{}",pathUrl);
            log.error("异常:{}",pathUrl);
        }
        ByteArrayOutputStream byteArrayOutputStream=new  ByteArrayOutputStream();
        byte[] buff=new byte[100];
        int rc=0;
        while (true){
            try {
                if(!((rc=inputStream.read(buff,0,100))>0))break;
            }catch (IOException e){
                log.error("minio down file error.  pathUrl:{}",pathUrl);
            }

 byteArrayOutputStream.write(buff,0,rc);       }
        return byteArrayOutputStream.toByteArray();
    }
}
